#include "attendancewin.h"
#include "ui_attendancewin.h"
#include <QDateTime>
#include <QSqlRecord>
#include <QThread>
#include <opencv.hpp>
#include <QSqlQuery>
#include <QSqlError>
#include <QJsonObject>
#include <QJsonDocument>
AttendanceWin::AttendanceWin(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::AttendanceWin)
{
    ui->setupUi(this);
    //qtcpServer当有客户端连会发送newconnection
    connect(&mserver, &QTcpServer::newConnection, this, &AttendanceWin::accept_client);
    mserver.listen(QHostAddress::Any,9999);//监听，启动服务器
    bsize = 0;

    //初始化数据库
   // initDatabase();

    createTables();
    //给sql模型绑定表格
    model.setTable("employee");
    if (!model.select()) {
        qDebug() << "表不存在或查询失败:" << model.lastError().text();
    }

    //创建一个线程
    QThread *thread = new QThread();
    //把QFaceObject对象移动到thread线程中执行
    fobj.moveToThread(thread);
    //启动线程
    thread->start();
    connect(this,&AttendanceWin::query,&fobj,&QFaceObject::face_query);
    //关联QFaceObject对象里面的send_faceid信号
    connect(&fobj,&QFaceObject::send_faceid,this, &AttendanceWin::recv_faceid);

}

AttendanceWin::~AttendanceWin()
{
    delete ui;
}


bool AttendanceWin::createTables() {
    QSqlQuery query;

    // 员工表
    QString employeeTable =
        "CREATE TABLE IF NOT EXISTS employee ("
        "   employeeID INTEGER PRIMARY KEY AUTOINCREMENT,"
        "   name TEXT NOT NULL,"
        "   sex TEXT CHECK(sex IN ('男', '女')),"
        "   birthday TEXT,"
        "   address TEXT,"
        "   phone TEXT,"
        "   faceID INTEGER UNIQUE,"
        "   headfile TEXT,"
        "   department TEXT DEFAULT '默认部门'"
        ")";

    // 考勤表
    QString attendanceTable =
        "CREATE TABLE IF NOT EXISTS attendance ("
        "   attendaceID INTEGER PRIMARY KEY AUTOINCREMENT,"
        "   employeeID INTEGER NOT NULL,"
        "   name TEXT,"
        "   department TEXT,"
        "   attendaceTime TEXT NOT NULL DEFAULT(datetime('now','localtime')),"
        "   checkType INTEGER NOT NULL CHECK(checkType IN (1, 2))," // 1:上班 2:下班
        "   status TEXT CHECK(status IN ('normal', 'late', 'early', 'absent')),"
        "   lateMinutes INTEGER DEFAULT 0,"
        "   earlyMinutes INTEGER DEFAULT 0"
        ")";

    // 考勤规则表
    QString ruleTable =
        "CREATE TABLE IF NOT EXISTS attendance_rules ("
        "   ruleID INTEGER PRIMARY KEY AUTOINCREMENT,"
        "   department TEXT UNIQUE NOT NULL,"
        "   workStartTime TEXT NOT NULL," // 格式: HH:MM
        "   workEndTime TEXT NOT NULL"
        ")";

    // 执行创建
    if(!query.exec(employeeTable)) {
        qCritical() << "创建员工表失败:" << query.lastError().text();
        return false;
    }

    if(!query.exec(attendanceTable)) {
        qCritical() << "创建考勤表失败:" << query.lastError().text();
        return false;
    }

    if(!query.exec(ruleTable)) {
        qCritical() << "创建规则表失败:" << query.lastError().text();
        return false;
    }

    return true;
}

bool AttendanceWin::initDatabase() {

    QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");
    db.setDatabaseName("AttendanceSystemDB.db"); // 修改为新的数据库名
    if (!db.open()) {
        qCritical() << "数据库打开失败:" << db.lastError().text();
        return false;
    }
    // 创建表结构
    return createTables();
}
//接受客户端连接
void AttendanceWin::accept_client()
{
    //获取与客户端通信的套接字
    msocket = mserver.nextPendingConnection();

    //当客户端有数据到达会发送readyRead信号
    connect(msocket,&QTcpSocket::readyRead,this,&AttendanceWin::read_data);
}

//读取客户端发送的数据
void AttendanceWin::read_data()
{
    QDataStream stream(msocket); //把套接字绑定到数据流
    stream.setVersion(QDataStream::Qt_5_14);

    if(bsize == 0){
        if(msocket->bytesAvailable()<(qint64)sizeof(bsize)) return ;
        //采集数据的长度
        stream>>bsize;
    }

    if(msocket->bytesAvailable() < bsize)//说明数据还没有发送完成，返回继续等待
    {
        return ;
    }
    QByteArray data;
    stream>>data;
    bsize = 0;
    if(data.size() == 0)//没有读取到数据
    {
        return;
    }

    //显示图片
    QPixmap mmp;
    mmp.loadFromData(data,"jpg");
    mmp = mmp.scaled(ui->picLb->size());
    ui->picLb->setPixmap(mmp);


    //识别人脸
    cv::Mat faceImage;
    std::vector<uchar> decode;
    decode.resize(data.size());
    memcpy(decode.data(),data.data(),data.size());
    faceImage = cv::imdecode(decode, cv::IMREAD_COLOR);

    //int faceid = fobj.face_query(faceImage); //消耗资源较多
    emit query(faceImage);

}

void AttendanceWin::recv_faceid(int64_t faceid)
{
    //qDebug()<<"00000"<<faceid;
    //从数据库中查询faceid对应的个人信息
    //给模型设置过滤器
    qDebug()<<"识别到的人脸id:"<<faceid;
    if(faceid < 0)
    {

        // *******************************************
        //没有识别出来不应该发送消息给客户端
//        QString sdmsg = QString("{\"employeeID\":\" \",\"name\":\"\",\"department\":\"\",\"time\":\"\"}");
//        msocket->write(sdmsg.toUtf8());//把打包好的数据发送给客户端

        return;
    }
    model.setFilter(QString("faceID=%1").arg(faceid));

//    //查询
//    model.select();
//    //判断是否查询到数据
//    if(model.rowCount() == 1)
//    {
//        //工号，姓名，部门，时间
//        //{employeeID:%1,name:%2,department:%3,time:%4}
//        QSqlRecord record = model.record(0);
//        QString sdmsg = QString("{\"employeeID\":\"%1\",\"name\":\"%2\",\"department\":\"%3\",\"time\":\"%4\"}")
//                .arg(record.value("employeeID").toString()).arg(record.value("name").toString())
//                .arg(record.value("department").toString())
//                .arg(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss"));


//        //把数据写入数据库--考勤表
//        QString insertSql = QString("insert into attendance(employeeID) values('%1')").arg(record.value("employeeID").toString());
//        QSqlQuery query;
//        if(!query.exec(insertSql))
//        {
//            QString sdmsg = QString("{\"employeeID\":\" \",\"name\":\"\",\"department\":\"\",\"time\":\"\"}");
//            msocket->write(sdmsg.toUtf8());//把打包好的数据发送给客户端
//            qDebug()<<query.lastError().text();
//            return ;
//        }else
//        {
//            msocket->write(sdmsg.toUtf8());//把打包好的数据发送给客户端
//        }
//    }


    // 查询员工信息
    model.select();
    if(model.rowCount() == 1) {
        QSqlRecord record = model.record(0);
        QString employeeID = record.value("employeeID").toString();
        QString name = record.value("name").toString();
        QString department = record.value("department").toString();
        QDateTime currentTime = QDateTime::currentDateTime();

        // 1. 获取部门考勤规则
        QSqlQuery ruleQuery;
        ruleQuery.prepare("SELECT workStartTime, workEndTime FROM attendance_rules WHERE department = ?");
        ruleQuery.addBindValue(department);

        if(!ruleQuery.exec() || !ruleQuery.next()) {
            QString errorMsg = "{\"employeeID\":\"\",\"name\":\"\",\"department\":\"\",\"time\":\"\",\"status\":\"no_rule\"}";
            msocket->write(errorMsg.toUtf8());
            return;
        }

        QTime workStartTime = QTime::fromString(ruleQuery.value("workStartTime").toString(), "HH:mm");
        QTime workEndTime = QTime::fromString(ruleQuery.value("workEndTime").toString(), "HH:mm");

        // 2. 判断考勤类型 (1:上班 2:下班)
        int checkType = (currentTime.time() < QTime(13, 0)) ? 1 : 2;

        // 3. 计算考勤状态和迟到/早退时间
        QString status = "normal";
        int timeDiff = 0;

        if(checkType == 1) { // 上班打卡
            if(currentTime.time() > workStartTime) {
                timeDiff = workStartTime.secsTo(currentTime.time()) / 60; // 计算迟到分钟数
                status = timeDiff > 0 ? "late" : "normal";
            }
        } else { // 下班打卡
            if(currentTime.time() < workEndTime) {
                timeDiff = currentTime.time().secsTo(workEndTime) / 60; // 计算早退分钟数
                status = timeDiff > 0 ? "early" : "normal";
            }
        }
        qDebug("迟到时间");
        qDebug()<<timeDiff;

        // 4. 检查重复打卡
        QSqlQuery checkQuery;
        checkQuery.prepare(
            "SELECT COUNT(*) FROM attendance WHERE "
            "employeeID = ? AND date(attendaceTime) = date(?) AND checkType = ?"
        );
        checkQuery.addBindValue(employeeID);
        checkQuery.addBindValue(currentTime.toString("yyyy-MM-dd HH:mm:ss"));
        checkQuery.addBindValue(checkType);

        if(checkQuery.exec() && checkQuery.next() && checkQuery.value(0).toInt() > 0) {
            QString errorMsg = QString("{\"employeeID\":\"%1\",\"name\":\"%2\",\"department\":\"%3\",\"time\":\"%4\",\"status\":\"duplicate\"}")
                             .arg(employeeID).arg(name).arg(department)
                             .arg(currentTime.toString("yyyy-MM-dd HH:mm:ss"));
            msocket->write(errorMsg.toUtf8());
            return;
        }

        // 5. 保存考勤记录（确保迟到/早退时间正确写入）
        QSqlQuery insertQuery;
        insertQuery.prepare(
            "INSERT INTO attendance ("
            "employeeID, name, department, attendaceTime, checkType, status, lateMinutes, earlyMinutes"
            ") VALUES (?, ?, ?, ?, ?, ?, ?, ?)"
        );
        insertQuery.addBindValue(employeeID);
        insertQuery.addBindValue(name);
        insertQuery.addBindValue(department);
        insertQuery.addBindValue(currentTime.toString("yyyy-MM-dd HH:mm:ss"));
        insertQuery.addBindValue(checkType);
        insertQuery.addBindValue(status);
        insertQuery.addBindValue(checkType == 1 ? timeDiff : 0);  // 迟到时间
        insertQuery.addBindValue(checkType == 2 ? timeDiff : 0);  // 早退时间

        if(!insertQuery.exec()) {
            QString errorMsg = "{\"employeeID\":\"\",\"name\":\"\",\"department\":\"\",\"time\":\"\",\"status\":\"db_error\"}";
            msocket->write(errorMsg.toUtf8());
            return;
        }

        // 6. 返回简化响应（仅5个字段）
        QString response = QString("{\"employeeID\":\"%1\",\"name\":\"%2\",\"department\":\"%3\",\"time\":\"%4\",\"status\":\"%5\"}")
                         .arg(employeeID).arg(name).arg(department)
                         .arg(currentTime.toString("yyyy-MM-dd HH:mm:ss"))
                         .arg(status);
        msocket->write(response.toUtf8());
    } else {
        QString errorMsg = "{\"employeeID\":\"\",\"name\":\"\",\"department\":\"\",\"time\":\"\",\"status\":\"not_found\"}";
        msocket->write(errorMsg.toUtf8());
    }
}
// 辅助函数：发送空响应
void AttendanceWin::sendEmptyResponse(QTcpSocket* socket) {
    QJsonObject response;
    response["error"] = "employee_not_found";
    response["message"] = "未找到员工信息";
    QJsonDocument doc(response);
    socket->write(doc.toJson());
}

// 辅助函数：发送错误响应
void AttendanceWin::sendErrorResponse(QTcpSocket* socket, const QString& errorCode, const QString& message) {
    QJsonObject response;
    response["error"] = errorCode;
    response["message"] = message;
    QJsonDocument doc(response);
    socket->write(doc.toJson());
}
